package gsp420.game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Vector;

import javax.swing.JPanel;


public class RTSGame extends JPanel implements
		MouseListener, MouseMotionListener, Runnable
{
	/** the one and only instance of my game*/
	private static RTSGame instance;

	/** singleton accessor */
	public static RTSGame getInstance()
	{
		if(instance == null)
			instance = new RTSGame();
		return instance;
	}
	
	private Rect dirtyRectangle = new Rect();
	
	/** generated serial id */
	private static final long serialVersionUID = 4661339889343844761L;

	/** display list... all of the game entities */
	Vector<Entity> gameEntities = new Vector<Entity>();
	/** entity controlled by the user via mouse clicks */
	Entity player;

	Point lastClick, lastmove;
	
	int NUM_ENTITIES = 1000;

	public static int GAME_RUNNING = 1;
	private int gameState = GAME_RUNNING;

	public boolean isRunning()
	{
		return gameState == GAME_RUNNING;
	}

	public void paintComponent(Graphics g)
	{
		// make sure that only a small portion of the screen updates
		g.setClip((int)dirtyRectangle.p.x, 
				(int)dirtyRectangle.p.y, 
				(int)dirtyRectangle.d.x, 
				(int)dirtyRectangle.d.y);
//		super.paintComponent(g);
		g.setColor(Color.WHITE);
		g.fillRect(0,0,getWidth(),getHeight());
		
		g.drawString("Hello World", 20, 20);
		// running the display list
		for (int i = 0; i < gameEntities.size(); ++i)
		{
			gameEntities.get(i).draw(g);
		}
		if(lastmove != null)
		{
			g.drawOval((int)lastmove.x-5, (int)lastmove.y-5, 
					10, 10);
		}
		if (lastClick != null)
		{
			g.drawString("x", (int) lastClick.x,
					(int) lastClick.y);
		}

		g.setColor(Color.RED);
		dirtyRectangle.draw(g);
		
		// remove the clip bounds
		g.setClip(null);

		dirtyRectangle.invalidate();
	}

	/** creates a game */
	private RTSGame()
	{
		// player is a "pointer", though there is no memory
		// access allowed
		player = new Entity();
		// TODO i should really be able to set the x/y and
		// size in the constructor...
		player.getDimension().set(10, 10);
		player.getVelocity().set(5, 3);
		// add the player to be managed anonymously by the
		// display list
		gameEntities.add(player);
		int x, y, s, r, g, b;
		for(int i = 0; i < NUM_ENTITIES; ++i)
		{
			x = (int)(Math.random() * 400);
			y = (int)(Math.random() * 300);
			s = (int)(Math.random() * 50)+5;

			r = (int)(Math.random() * 255);
			g = (int)(Math.random() * 255);
			b = (int)(Math.random() * 255);
			Entity e = new 
			//WeirdThing
			Entity(x, y, s, new Color(r,g,b));
			gameEntities.add(e);
		}
		// must be added here so java knows to listen to the
		// mouse
		addMouseListener(this);
		addMouseMotionListener(this);
		
		dirtyRectangle.p.set(0,0);
		dirtyRectangle.d.set(800,600);
	}

	public void mouseClicked(MouseEvent e)
	{
	}

	public void mouseEntered(MouseEvent e)
	{
	}

	public void mouseExited(MouseEvent e)
	{
	}

	public void mouseReleased(MouseEvent e)
	{
	}
	public void mouseDragged(MouseEvent e){}
	public void mouseMoved(MouseEvent e)	{
		lastmove = new Point();
		lastmove.set(e);
		
		Rect m = new Rect();
		m.p.x = lastmove.x-10;
		m.p.y = lastmove.y-10;
		m.d.x = 20;
		m.d.y = 20;
		dirtyRectangle.add(m);
		System.out.println(dirtyRectangle);
	}

	public void mousePressed(MouseEvent e)
	{
		Point click = new Point();
		// where the mouse was clicked
		click.set(e);
		// where the player is
		Point pos = player.getPosition();
		// distance between the player and the click
		Point delta = new Point(click);
		delta.subtract(pos);

		dirtyRectangle.p.set(0,0);
		dirtyRectangle.d.set(800,600);

		// make the player move there in one second...
		player.getVelocity().set(delta);
		player.getVelocity().setHypotinuse(20);
		lastClick = click;
		repaint();
	}

	public static void sleep(int ms)
	{
		try
		{
			Thread.sleep(ms);
		} catch (Exception e)
		{
		}
	}

	public void update(int ms)
	{
		Rect entityRect = new Rect();
		if (ms != 0)
		{
			for (int i = 0; i < gameEntities.size(); ++i)
			{
				entityRect.set(gameEntities.get(i));
				// if the entity updated
				if(gameEntities.get(i).update(ms))
				{
					if(dirtyRectangle.isValid())
					{
						dirtyRectangle.add(entityRect);
						entityRect.set(gameEntities.get(i));
						dirtyRectangle.add(entityRect);
					}
					else
					{
						dirtyRectangle.set(entityRect);
						entityRect.set(gameEntities.get(i));
						dirtyRectangle.add(entityRect);
					}
				}
			}
		}
	}

	public void run()
	{
		long now, then = System.currentTimeMillis(), passed;
		while (isRunning())
		{
			// time calculation
			now = System.currentTimeMillis();
			passed = now - then;
			then = now;
			// update
			update((int) passed);
			// throttle code
			sleep(20);
			// "draw"
			repaint();
		}
	}
}
